import type { ISmsResponse } from '@/modules/sms/sms.service'
import { HttpException, HttpStatus, Injectable } from '@nestjs/common'
import { InjectRepository } from '@nestjs/typeorm'

import { DataSource, Repository } from 'typeorm'

import { BaseService } from '@/common/base/base.service'
import { SmsService } from '@/modules/sms/sms.service'
import { JwtTool } from '@/shared/utils/tool'
import { LoginPlayerUserDto, UpdatePlayerUserDto } from './dto/player-user.dto'
import { PlayerUser } from './entities/player-user.entity'

@Injectable()
export class PlayerUserService extends BaseService<PlayerUser, 'playerUserId'> {
  private jwt = new JwtTool()
  constructor(
    @InjectRepository(PlayerUser)
    private readonly repo: Repository<PlayerUser>,
    private readonly smsService: SmsService,
    private readonly dataSource: DataSource,
  ) {
    super(repo)
  }

  async findAndUpdateUserInfo(uid: string) {
    const { lastLoginTime, maxRoleLevel } = await this.smsService.getGameUserInfoByUid({ uid })
    await this.updateByUid(uid, { lastLoginTime, maxRoleLevel })
    const user = await this.findOne({ where: { uid } })
    return user
  }

  async findUserExpress(uid: string): Promise<PlayerUser['expressInfo']> {
    if (!uid) {
      throw new HttpException('请先登录', HttpStatus.UNAUTHORIZED)
    }
    const response = await this.findOne({ where: { uid }, select: ['expressInfo'] })
    return response.expressInfo
  }

  async updateByUid(uid: string, data: UpdatePlayerUserDto) {
    return this.repo.update({ uid }, data)
  }

  async loginOrRegister(data: LoginPlayerUserDto): Promise<ISmsResponse<{ token: string, uid: string }>> {
    const response = await this.smsService.userLoginByPhone(data)
    // const response = await this.smsService.getUserInfoByPhone(data)
    const userInfo = response.data
    if (!userInfo?.uid) {
      return { status: false, message: response.message }
    }

    let playerUserData: PlayerUser
    playerUserData = await this.repository.findOne({ where: { uid: userInfo.uid } })
    const params = {
      username: userInfo.username,
      phone: data.phone,
      dynamic: JSON.stringify(userInfo),
      regTime: userInfo.regTime,
    }

    if (!playerUserData) {
      // 他的登录好像自动带着注册的
      // const response = await this.smsService.userRegister(data)
      await this.save({ ...params, uid: userInfo.uid })
      playerUserData = await this.repository.findOne({ where: { uid: userInfo.uid } })
    }
    else if (playerUserData) {
      if (playerUserData.uid !== userInfo.uid) {
        return { status: false, message: '用户 ID 不一致' }
      }
      await this.update(playerUserData.playerUserId, params)
    }

    const token = this.jwt.generateToken(playerUserData)

    return {
      status: true,
      message: response.message,
      data: {
        token,
        uid: playerUserData.uid,
      },
    }
  }

  async reservation(userUid: string, inviteUserUid?: string) {
    return await this.dataSource.transaction(async (manager) => {
      // 处理邀请人逻辑
      if (inviteUserUid) {
        const inviteUser = await manager.findOne(PlayerUser, {
          where: { uid: inviteUserUid },
        })

        if (!inviteUser) {
          throw new HttpException('邀请人不存在', HttpStatus.BAD_REQUEST)
        }

        // 邀请人次数+1
        await manager.update(PlayerUser, { uid: inviteUserUid }, { inviteCount: () => 'inviteCount + 1' })
      }

      // 更新当前用户预约状态
      await manager.update(PlayerUser, { uid: userUid }, { isReserved: true, invitedByUid: inviteUserUid || null })
    })
  }
}
